package aliyunlog

import (
	"regexp"
	"os"
	"time"
	"fmt"
	"errors"
	"encoding/json"
	"strings"
	"log/syslog"
	"gateway/utils"
)

const (
	LOGPREFIX = "etcphplog"
)

type Content struct {
	Remark string `json:"remark"`
	State  string `json:"state "` // ok-成功；fail失败
}

// 写日志
// business 对应业务
// operate 操作名称
// content 日志内容，支持string、Content类型
// monitor 是否进行监控，若为true，content必须为Content类型
func Write(business string, operate string, content interface{}, monitor bool) error {
	defer utils.RoutineRecover()
	contentStr, err := formatContent(content)
	if err != nil {
		return err
	}

	business = regexp.MustCompile(`\s+`).ReplaceAllString(business, "")
	operate = regexp.MustCompile(`\s+`).ReplaceAllString(operate, "")
	now := time.Now()
	date := now.Format("2006-01-02T15:04:05")
	logs := business + " " + operate + " " + date + " " + hostname() + " " + contentStr
	fmt.Println(logs)

	// 记录普通日志
	err = logLocal0(logs)
	if err != nil {
		return err
	}

	if monitor {
		logLocal1(business, operate, content.(Content), now)
	}

	return nil
}

// 记录监控日志
func logLocal1(business string, operate string, content Content, now time.Time) error {
	if hostname() == "develop" {
		operate += "_in_deveopment"
	}

	if content.Remark == "" {
		content.Remark = "noremark"
	}

	s1 := regexp.MustCompile(`\s+`).ReplaceAllString(content.Remark, "")
	if len(s1) > 3750 {
		s1 = s1[:3750]
	}

	s2 := strings.Replace(content.Remark, "\n", " ", -1)
	if len(s2) > 3750 {
		s2 = s2[:3750]
	}

	logs := []string{
		business,
		operate,
		//阿里云监控日志发现remark限定在7500 ~ 8000字节之间，否则监控日志无法同步上去，因为需要存两份，所以每份取最多3750
		s1,
		now.Format("2006-01-02T15:04:05"),
		now.Format("2006"),
		now.Format("01"),
		now.Format("02"),
		now.Format("15"),
		now.Format("04"),
		now.Format("05"),
		hostname(),
		content.State,
		"1",// 占位符
		s2,
	}
	logStr := strings.Join(logs, " ")
	logger, err := syslog.New(syslog.LOG_LOCAL1, LOGPREFIX)
	if err != nil {
		return err
	}

	return logger.Info(logStr)
}

// 记录普通日志
func logLocal0(logs string) error {
	logger, err := syslog.New(syslog.LOG_LOCAL0, LOGPREFIX)
	if err != nil {
		return err
	}

	return logger.Info(logs)
}

// 格式化日志内容
func formatContent(content interface{}) (string, error) {
	contentStr := ""
	switch t := content.(type) {
	case string:
		contentStr = content.(string)
		if len(contentStr) == 0 {
			return "", errors.New("日志内容为空")
		}
	case Content:
		contentBytes, err := json.Marshal(content)
		if err != nil {
			return "", err
		}
		contentStr = utils.ByteToStr(contentBytes)
	default:
		return "", errors.New("content类型" + t.(string) + "无效")
	}

	return regexp.MustCompile(`\n+`).ReplaceAllString(contentStr, " "), nil
}

// 获取主机名，若获取失败返回"unknownhost"
func hostname() string {
	host, err := os.Hostname()
	if err != nil {
		host = "unknownhost"
	}

	return host
}
